#include <asl_core.h>
#include <asl_executor.h>
#include <asl_executor_exp.h>
#include <asl_executor_global.h>

extern executor_info_t global_executor;

/**
 *
 * @param gs
 * @param var_table
 * @return
 */
executor_control_t *executor_global_run(global_statement_t *gs, hash_t *var_table) {
    value_t *v, *gv, *dv;
    v = executor_exp_run(gs->e, var_table);
    gv = (value_t *) hash_find(global_executor.var_table, gs->var, gs->var_len);
    if (is_empty(v) && is_empty(gv)) {
        v = value_create_null();
        gv = value_create_null();
        value_incr_quote(v);
        value_incr_quote(gv);
        v->is_global = 1;
        hash_insert_or_update(global_executor.var_table, gs->var, gs->var_len, (void *) gv);
        hash_insert_or_update(var_table, gs->var, gs->var_len, (void *) v);
    } else if (is_empty(v) && is_not_empty(gv)) {
        v = value_duplicate(gv, 0);
        value_incr_quote(v);
        v->is_global = 1;
        hash_insert_or_update(var_table, gs->var, gs->var_len, (void *) v);
    } else if (is_not_empty(v) && is_empty(gv)) {
        gv = value_duplicate(v, 0);
        value_incr_quote(v);
        value_incr_quote(gv);
        v->is_global = 1;
        hash_insert_or_update(var_table, gs->var, gs->var_len, (void *) v);
        hash_insert_or_update(global_executor.var_table, gs->var, gs->var_len, (void *) gv);
    } else {
        if (gv->refer_count == 1) {
            hash_delete(global_executor.var_table, gs->var, gs->var_len);
        }
        value_decr_quote(gv);
        dv = value_duplicate(v, 0);
        value_incr_quote(dv);
        value_incr_quote(v);
        v->is_global = 1;
        hash_insert_or_update(var_table, gs->var, gs->var_len, (void *) v);
        hash_insert_or_update(global_executor.var_table, gs->var, gs->var_len, (void *) dv);
    }
    return executor_create_control(executor_control_type_global);
}